package nz.ac.massey.spidernetpn.gui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;

import nz.ac.massey.spidernetpn.database.GraphDatabase;
import nz.ac.massey.spidernetpn.gui.MainGui.LoadThread;
import nz.ac.massey.spidernetpn.webcrawler.FoundMaxException;
import nz.ac.massey.spidernetpn.webcrawler.WebCrawler;
import edu.uci.ics.jung.algorithms.layout.*;
import edu.uci.ics.jung.algorithms.layout.util.Relaxer;
import edu.uci.ics.jung.algorithms.layout.util.VisRunner;
import edu.uci.ics.jung.algorithms.util.IterativeContext;
import edu.uci.ics.jung.graph.DirectedGraph;
import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.ObservableGraph;
import edu.uci.ics.jung.graph.event.GraphEvent;
import edu.uci.ics.jung.graph.event.GraphEventListener;
import edu.uci.ics.jung.graph.util.Graphs;
import edu.uci.ics.jung.visualization.BasicVisualizationServer;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.layout.LayoutTransition;
import edu.uci.ics.jung.visualization.renderers.*;
import edu.uci.ics.jung.visualization.util.Animator;

public class GuiPrototype extends JPanel implements GuiInterface {
	private static final long serialVersionUID = 6962983038658967662L;
	Thread loadThread;
	Object lock = new Object();
	private static WebCrawler crawler = new WebCrawler(true);
	private JFrame frame = new JFrame("Web-Clawer");
	private String name;
	private JTextField urlField;
	private JSlider slider;
	private JProgressBar progressBar;
	//private  JButton goButton;
	private static JButton  stopButton;
	private GraphDatabase gDB = new GraphDatabase();
	public static MainGui main = new MainGui();
	private DirectedGraph<URL,Integer> graph;

	boolean shouldStop = false;
	JTextField progressTextField;
	BasicVisualizationServer<URL, Integer> vs=null;
	JFrame GraphFrame = new JFrame("Simple Graph View");
	JPanel GraphPanel = new JPanel();
	
	

	public void Frame() {
		// TODO Auto-generated method stub
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setJMenuBar(createMenuBar());
		frame.getContentPane().add(graphPane());
		frame.getContentPane().add(createProgressBar(),BorderLayout.SOUTH);
		frame.getContentPane().add(createSlider(), BorderLayout.EAST);
		
		frame.pack();
		frame.setSize(700, 700);
		frame.setVisible(true);
		
	}

	JPanel drawingPane;	
	public JPanel graphPane(){

		Dimension area;
		 area = new Dimension(50,50);
		 drawingPane = new DrawingPane();
	        drawingPane.setBackground(Color.YELLOW);
	        JScrollPane scroller = new JScrollPane(drawingPane);
	        scroller.setPreferredSize(new Dimension(200,200));
	       
		return drawingPane;
		
	}
	
	 public class DrawingPane extends JPanel {
	        protected void paintComponent(Graphics g) {
	            super.paintComponent(g);
	           
	            
	            crawler.addActionListener(new ActionListener() {
	    			@Override
	    			public void actionPerformed(ActionEvent e) {
	    				//get the DirectedGraph
	    				graph = crawler.getGraph();
	    				//Draw the graph and display it
	    				//System.out.println("Drawn something new I hope. Size: " + graph.getEdgeCount());

	    				if((graph.getEdgeCount()%100==0)||(graph.getEdgeCount()<10&&graph.getEdgeCount()>1)){
		    				System.out.println("An action has been called");
		    				drawingPane.removeAll();
		    	/*
		    				Layout<URL, Integer> layout = new FRLayout<URL, Integer>(graph);
		    				layout.setSize(new Dimension(800,800)); // sets the initial size of the layout space
		    				Dimension preferredSize = new Dimension(1000,1000);
		    				vs = new BasicVisualizationServer<URL, Integer>(layout, preferredSize);
		    				
		    				vs.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<URL>());
		    				//vs.repaint();
		    				//vs.setVisible(true);
		    				//drawingPane.add(vs);
		    	 
		    	 */
		    				Drawing(graph);
		    				
		    				GraphFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		    				GraphFrame.getContentPane().add(vs);
		    				//comment to stop new window opening
		    				//GraphFrame.add(frame);
		    				GraphFrame.pack();
		    				//drawingPane.add(GraphFrame);
		    				
		    				GraphFrame.setVisible(true);
		    				
		    				// TODO Now draw it! You need to put the code that draws the graph in here.
		    				System.out.println("Drawn something new I hope. Size: " + graph.getEdgeCount());
	    				}
	    				if(graph.getEdgeCount()>201){
	    					//FOr testing stop after 200 nodes
	    					crawler.stop();
	    				}

	    			}
	    		});
	        }
	    }
	
	 public void Drawing(DirectedGraph<URL, Integer> g) {
		 	Layout<URL, Integer> layout = new CircleLayout<URL, Integer>(g);
			layout.setSize(new Dimension(800,800)); // sets the initial size of the layout space
			Dimension preferredSize = new Dimension(1000,1000);
			vs = new BasicVisualizationServer<URL, Integer>(layout, preferredSize);
			vs.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<URL>());
			vs.repaint();
			drawingPane.add(vs);
	 }
	 
	public JMenuBar createMenuBar() {
		// TODO Auto-generated method stub	
		JMenuBar menuBar = new JMenuBar();
		// Define and add two drop down menu to the menubar
		JMenu fileMenu = new JMenu("File");
		JLabel Url = new JLabel("Enter url: ");
		urlField = new JTextField();
		urlField.setText("http://www.google.com");
		urlField.setColumns(20);
		JButton goButton = new JButton("Go");
		stopButton = new JButton("Stop");
		menuBar.add(fileMenu);
		menuBar.add(Url);
		menuBar.add(urlField);
		menuBar.add(goButton);
		menuBar.add(stopButton);
		// Create and add simple menu item to one of the drop down menu
		JMenuItem newAction = new JMenuItem("New");
		JMenuItem openAction = new JMenuItem("Open");
		JMenuItem saveAction = new JMenuItem("Save");
		JMenuItem exitAction = new JMenuItem("Exit");
		fileMenu.add(newAction);
		fileMenu.add(openAction);
		fileMenu.add(saveAction);
		fileMenu.addSeparator();
		fileMenu.add(exitAction);

		goButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				start();
				startLoading();
			}
		});
		
		stopButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				crawler.stop();
				main.stopLoading();
			}
		});

		saveAction.addActionListener(new ActionListener() {
			@SuppressWarnings("deprecation")
			public void actionPerformed(ActionEvent e1){
				JFrame saveFrame = new JFrame();
		        JTextField field = new JTextField();
		        JButton ok = new JButton("OK");
		        
 		        saveFrame.setSize(550, 30);
		        field.setSize(500, 30);
		        saveFrame.add(field);
		        saveFrame.add(ok, BorderLayout.EAST);
			   // saveFrame.setVisible(true);
			    saveFrame.pack();
			    saveFrame.show();
				name = field.getText();
				ok.addActionListener(new ActionListener(){
					public void actionPerformed(ActionEvent e2){
						if (!name.isEmpty()) {
							if (gDB.saveGraph(name, graph)){
								JOptionPane.showMessageDialog(frame, "Save succeed");
							}
							else {
									JOptionPane.showMessageDialog(frame,
									"Unable to save","Error", 
									JOptionPane.ERROR_MESSAGE);
							}
						}
							else {
								JOptionPane.showMessageDialog(frame, "Please give a name to graph you want to save");
						}
					}
					}
				);
			}
		});
		
		openAction.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e1) {
				final DefaultListModel listModel = new DefaultListModel();			
				JFrame loadFrame = new JFrame();
		        JTextField field = new JTextField();    
		        JButton load = new JButton("Load");
		        final JButton remove = new JButton("Remove");
		        loadFrame.setSize(550, 300);
		        field.setSize(500, 300);
		        loadFrame.add(field, BorderLayout.NORTH);
		        loadFrame.add(load, BorderLayout.CENTER);
		        loadFrame.add(remove, BorderLayout.SOUTH);
			    loadFrame.pack();
			    loadFrame.show();
			    
				List gList = gDB.getListOfStoredGraphs();
 
				while (gList.iterator().next()!= null)
				{
					Object obj = gList.iterator().next();
					listModel.addElement(obj);			
				}
				
				final JList L = new JList(listModel);
				L.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		        L.setSelectedIndex(0);
		      //L.addListSelectionListener(this);
		        L.setVisibleRowCount(5);

		        
		        //remove method
				remove.addActionListener(new ActionListener(){
					public void actionPerformed(ActionEvent e) {
			            int index = L.getSelectedIndex();
			            listModel.remove(index);

			            int size = listModel.getSize();

			            if (size == 0) { //Nobody's left, disable removing.
			                remove.setEnabled(false);

			            } else { //Select an index.
			                if (index == listModel.getSize()) {
			                    //removed item in last position
			                    index--;
			                }

			                L.setSelectedIndex(index);
			                L.ensureIndexIsVisible(index);
			            }
			        }
				});
				
				//get a name from the list
				String name = listModel.getElementAt(
                              L.getSelectedIndex()).toString();
	
				//Display the selected graph
				DirectedGraph<URL, Integer> savedGraph = null;
				try {
					savedGraph = gDB.loadCustomGraph(name);
					Drawing(savedGraph);
					
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				}
		});

		exitAction.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				System.exit(0);
			}
		});
		return menuBar;
	}
	
	
	
	public JPanel createProgressBar() {
		// TODO Auto-generated method stub
		JPanel panel = new JPanel();
		JTextField progressTextField = new JTextField();
		progressBar = new JProgressBar();
		progressBar.setStringPainted(true);

		panel.setLayout(new GridLayout(0, 1));
		panel.add(new JLabel("Load Status"));
		panel.add(progressBar, BorderLayout.SOUTH);
		return panel;
	}

	
	public JPanel createSlider() {
		// TODO Auto-generated method stub
		int min = -5, max = 5, inc = 0;
		
		slider = new JSlider(JSlider.VERTICAL, min, max, inc);
		slider.setMajorTickSpacing(5);
		slider.setMinorTickSpacing(1);
		slider.setPaintTicks(true);
		slider.setSnapToTicks(true);
		slider.setPaintLabels(true);
		JPanel panel = new JPanel();
		panel.add(slider, BorderLayout.SOUTH);
		return panel;
	}

	
	public void errorMsg() {
		// TODO Auto-generated method stub
		JOptionPane.showMessageDialog(frame,
				"Please enter URL with correct format start with http://",
				"Error", JOptionPane.ERROR_MESSAGE);
	}


	public String url() {
		// TODO Auto-generated method stub
		return urlField.getText();
	}
	

	public void start(){
		try {
			crawler.submit(url());
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (FoundMaxException e) {
			e.printStackTrace();
		}
	}

	public void startLoading() {
		if (loadThread == null) {
			loadThread = new LoadThread();
			shouldStop = false;
			loadThread.start();
			validate();
		}
	}

	class LoadThread extends Thread {
		public void run() {
			int min = 0;
			int max = 100;
			progressBar.setValue(min);
			progressBar.setMinimum(min);
			progressBar.setMaximum(max);
			Runnable runner = new Runnable() {
				public void run() {
					int value = progressBar.getValue();
					value++;
					progressBar.setValue(value);
					progressTextField.setText("" + value);
				}
			};
			for (int i = min; i <= max; i++) {
				try {
					SwingUtilities.invokeAndWait(runner);
				} catch (InvocationTargetException e) {
					break;
				} catch (InterruptedException e) {
					// Ignore Exception
				}
				synchronized (lock) {
					if (shouldStop)
						break;
					try {
						lock.wait(100);
					} catch (InterruptedException e) {
						// Ignore Exception
					}
				}
			}
			loadThread = null;
		}
	}
	
	/**
	 * @param args
	 */

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		final GuiPrototype a = new GuiPrototype();
		a.Frame();
	}


}
